package com.ikun.admin.modules.sys.iservice.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ikun.admin.common.constant.CommonCharactersConstant;
import com.ikun.admin.modules.auth.utils.SecurityUtil;
import com.ikun.admin.modules.sys.entity.Dict;
import com.ikun.admin.modules.sys.entity.Notice;
import com.ikun.admin.modules.sys.entity.User;
import com.ikun.admin.modules.sys.iservice.IDictAndNoticeService;
import com.ikun.admin.modules.sys.service.DictService;
import com.ikun.admin.modules.sys.service.NoticeService;
import com.ikun.admin.modules.sys.service.UserService;
import com.ikun.admin.modules.sys.vo.*;
import com.ikun.common.exception.MyException;
import com.ikun.common.result.Result;
import com.ikun.common.search.PageData;
import com.ikun.common.search.PageResult;
import com.ikun.common.search.build.QueryBuilder;
import com.ikun.common.search.build.ResultBuilder;
import com.ikun.common.utils.DataCopy;
import com.ikun.common.validate.group.AddGroup;
import com.ikun.common.validate.group.UpdateGroup;
import com.ikun.common.validate.validator.ValidateExecutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @ClassName IDictAndNoticeServiceImpl
 * @Description:
 * @CreateDate: 2024/7/17 9:29
 */
@Service
public class IDictAndNoticeServiceImpl implements IDictAndNoticeService {

    //通知
    private static final Integer NOTICE_TYPE_NOTICE = 1;
    //公告
    private static final Integer NOTICE_TYPE_ANNOUNCEMENT = 0;
    //状态-发布
    private static final Integer NOTICE_STATUS_PUBLISHED = 0;
    //状态-撤销
    private static final Integer NOTICE_STATUS_REVOKED = 1;
    @Autowired
    private NoticeService noticeService;

    @Autowired
    private DictService dictService;

    @Autowired
    private UserService userService;


    @Override
    public Result<PageResult<NoticeListResultVo>> noticeList(PageData<NoticeListParamVo> pageData) {
        NoticeListParamVo noticeListParamVo = pageData.getCondition();
        PageData.PageParam pageParam = pageData.getPageParam();
        Page<Notice> noticePage = new Page<Notice>().setCurrent(pageParam.getCurrent()).setSize(pageParam.getSize());
        QueryWrapper<Notice> noticeQueryWrapper = new QueryWrapper<>();
        Boolean build = QueryBuilder.build(noticeQueryWrapper, noticeListParamVo);
        if (!build) {
            return new Result<PageResult<NoticeListResultVo>>().success(PageResult.emptyPageResult());
        }
        noticeService.page(noticePage, noticeQueryWrapper);

        List<NoticeListResultVo> resultVoList = new ArrayList<>();
        if (noticePage.getRecords().size() > 0) {
            ResultBuilder.buildResult(noticePage.getRecords(), resultVoList, NoticeListResultVo.class);

            Map<Long, Notice> noticeMap = noticePage.getRecords().stream().collect(Collectors.toMap(Notice::getId, notice -> notice));
            List<User> userList = userService.list(new QueryWrapper<>());
            Map<Long, User> userMap = userList.stream().collect(Collectors.toMap(User::getId, user -> user));
            resultVoList.stream().forEach(item -> {
                Notice notice = noticeMap.get(item.getId());
                Optional.ofNullable(notice).ifPresent(notice1 -> {
                    Optional.ofNullable(notice1.getReceiverIds()).ifPresent(receiverIds -> {
                        String[] userIdArr = receiverIds.split(CommonCharactersConstant.SEMICOLON);
                        ArrayList<String> receiverList = new ArrayList<>();
                        for (String userId : userIdArr) {
                            User user = userMap.get(Long.parseLong(userId));
                            Optional.ofNullable(user).ifPresent(user1 -> receiverList.add(user1.getUsername()));
                            item.setReceiverList(receiverList);
                        }
                    });
                });
            });
        }
        return new Result<PageResult<NoticeListResultVo>>().success(PageResult.getInstance(noticePage.getTotal(), resultVoList));
    }

    @Override
    public Result<NoticeDetailVo> noticeDetail(Long id) {
        Notice notice = noticeService.getById(id);
        NoticeDetailVo noticeDetailVo = DataCopy.copyToObj(notice, NoticeDetailVo.class);
        if (Objects.equals(notice.getType(), NOTICE_TYPE_NOTICE)) {
            String[] split = notice.getReceiverIds().split(CommonCharactersConstant.SEMICOLON);

            List<Long> userIdList = Arrays.stream(split).map(Long::parseLong).collect(Collectors.toList());
            if (userIdList.size() > 0) {
                List<User> userList = userService.list(new QueryWrapper<User>().lambda().in(User::getId, userIdList));
                List<String> realNameList = userList.stream().map(User::getRealName).collect(Collectors.toList());
                noticeDetailVo.setReceiverList(realNameList);
            }

        }


        return new Result<NoticeDetailVo>().success(noticeDetailVo);
    }

    @Override
    @Transactional
    public Result<String> addOrUpdateNotice(NoticeAddOrUpdateVo noticeAddOrUpdateVo) {
        if (Objects.isNull(noticeAddOrUpdateVo.getId())) {
            ValidateExecutor.execute(noticeAddOrUpdateVo, AddGroup.class);
            Long currentUserId = SecurityUtil.getCurrentUserId();

            Notice notice = DataCopy.copyToObj(noticeAddOrUpdateVo, Notice.class);
            notice.setSenderId(currentUserId);
            notice.setStatus(0);
            if (Objects.equals(notice.getType(), 1)) {
                String receiverIds = this.validateAndGetReceiverIds(noticeAddOrUpdateVo);
                notice.setReceiverIds(receiverIds);
            }
            noticeService.save(notice);
        } else {
            ValidateExecutor.execute(noticeAddOrUpdateVo, UpdateGroup.class);
            Notice notice = DataCopy.copyToObj(noticeAddOrUpdateVo, Notice.class);
            if (Objects.equals(notice.getType(), 1)) {
                String receiverIds = this.validateAndGetReceiverIds(noticeAddOrUpdateVo);
                notice.setReceiverIds(receiverIds);
            }
            noticeService.update(new UpdateWrapper<Notice>()
                    .lambda().eq(Notice::getId, notice.getId())
                    .set(Notice::getReceiverIds, notice.getReceiverIds())
                    .set(Notice::getContent, notice.getContent())
                    .set(Notice::getTitle, notice.getTitle()));
        }
        return new Result<String>().success("操作成功");
    }

    private String validateAndGetReceiverIds(NoticeAddOrUpdateVo noticeAddOrUpdateVo) {
        if (Objects.isNull(noticeAddOrUpdateVo.getReceiverList()) || noticeAddOrUpdateVo.getReceiverList().size() == 0) {
            throw new MyException("当前发布类型为通知,请至少选择一个通知对象");
        }
        StringBuilder receiverIds = new StringBuilder("");
        noticeAddOrUpdateVo.getReceiverList().forEach(userId -> receiverIds.append(userId).append(CommonCharactersConstant.SEMICOLON));
        return receiverIds.toString();
    }

    @Override
    @Transactional
    public Result<String> deleteNotice(Long id) {
        noticeService.removeById(id);
        return new Result<String>().success("操作成功");
    }

    @Override
    public Result<PageResult<DictCommonResultVo>> dictList(PageData<DictListParamVo> pageData) {

        DictListParamVo dictListParamVo = pageData.getCondition();
        PageData.PageParam pageParam = pageData.getPageParam();
        QueryWrapper<Dict> dictQueryWrapper = new QueryWrapper<>();
        Page<Dict> dictPage = new Page<Dict>().setCurrent(pageParam.getCurrent()).setSize(pageParam.getSize());
        Boolean build = QueryBuilder.build(dictQueryWrapper, dictListParamVo);
        if (!build) {
            return new Result<PageResult<DictCommonResultVo>>().success(PageResult.emptyPageResult());
        }
        dictService.page(dictPage, dictQueryWrapper);

        List<DictCommonResultVo> resultList = new ArrayList<>();
        if (dictPage.getRecords().size() > 0) {
            DataCopy.copyToListObj(dictPage.getRecords(), resultList, DictCommonResultVo.class);
        }
        return new Result<PageResult<DictCommonResultVo>>().success(PageResult.getInstance(dictPage.getTotal(), resultList));
    }

    @Override
    public Result<DictCommonResultVo> dictDetail(Long id) {
        Dict dict = dictService.getById(id);
        DictCommonResultVo dictCommonResultVo = DataCopy.copyToObj(dict, DictCommonResultVo.class);
        return new Result<DictCommonResultVo>().success(dictCommonResultVo);
    }

    @Override
    @Transactional
    public Result<String> addOrUpdateDict(DictCommonResultVo dictAddOrUpdateVo) {
        ValidateExecutor.execute(dictAddOrUpdateVo, null);
        List<Dict> dictList = dictService.list(new QueryWrapper<Dict>().lambda()
                .eq(Dict::getCluster, dictAddOrUpdateVo.getCluster())
                .ne(Objects.nonNull(dictAddOrUpdateVo.getId()), Dict::getId, dictAddOrUpdateVo.getId()));

        if (dictList.size() > 0) {
            dictList.stream().forEach(item -> {
                if (Objects.equals(item.getLabel(), dictAddOrUpdateVo.getLabel()) || Objects.equals(item.getValue(), dictAddOrUpdateVo.getValue())) {
                    throw new MyException("该分组下的字典值或字典标签已存在");
                }
            });
        }

        if (Objects.isNull(dictAddOrUpdateVo.getId())) {
            //新增
            Dict dict = DataCopy.copyToObj(dictAddOrUpdateVo, Dict.class);
            dictService.save(dict);
        } else {
            //修改
            dictService.update(new UpdateWrapper<Dict>().lambda().eq(Dict::getId, dictAddOrUpdateVo.getId())
                    .set(Dict::getCluster, dictAddOrUpdateVo.getCluster())
                    .set(Dict::getValue, dictAddOrUpdateVo.getValue())
                    .set(Dict::getLabel, dictAddOrUpdateVo.getLabel())
                    .set(Dict::getRemark, dictAddOrUpdateVo.getRemark()));
        }
        return new Result<String>().success("操作成功");
    }

    @Override
    public Result<String> deleteDict(Long id) {
        dictService.removeById(id);
        return new Result<String>().success("操作成功");
    }

    @Override
    public Result<List<DictCommonResultVo>> selectDictByGroup(String cluster) {
        List<Dict> dictList = dictService.list(new QueryWrapper<Dict>().lambda().eq(Dict::getCluster, cluster));
        List<DictCommonResultVo> dictCommonResultVoList = DataCopy.copyToListObj(dictList, DictCommonResultVo.class);

        return new Result<List<DictCommonResultVo>>().success(dictCommonResultVoList);
    }

    @Override
    public Result<Set<String>> selectClusterList() {
        List<Dict> dictList = dictService.list(new QueryWrapper<Dict>());
        Set<String> dictClusterSet = dictList.stream().map(Dict::getCluster).collect(Collectors.toSet());
        return new Result<Set<String>>().success(dictClusterSet);
    }

    @Override
    public Result<String> updateNoticeStatus(Long id) {

        noticeService.update(new UpdateWrapper<Notice>().lambda().eq(Notice::getId, id).set(Notice::getStatus,  NOTICE_STATUS_REVOKED));

        return new Result<String>().success("操作成功");
    }


}
